---
title: GetUserPrinter
summary: Reads a user's extensionAttribute2 attribute, hard-wired to the internal directory domain.
status: draft
owner: "Not determined from source"
last_reviewed: 2026-09-22
---

# GetUserPrinter (OP-17)

## Request and response

| Part | Type | Description |
| --- | --- | --- |
| `inUserId` | `String` | The `SamAccountName` to look up. No domain parameter is offered to the caller. |

| Part | Type | Description |
| --- | --- | --- |
| `<return>` | `ADServiceResponse` | `Response` (`EResponse` code) and `Message` (the `extensionAttribute2` attribute value on success). |

## WebMethod attributes

`<WebMethod()>` — bare, no arguments supplied.

## Steps

1. No access check is performed ([BR-06](../business-rules.md#br-06-read-only-directory-queries-are-not-access-controlled)).
2. Initialize `myStruc.Response = Success`, `myStruc.Message = String.Empty`.
3. In a `Try` block, call H2 `GetUserPrincipal` with `inExternalDomain` **hard-wired to `False`** — the internal domain only — per the authored comment `'Assume internal domain` ([BR-31](../business-rules.md#br-31-the-printer-attribute-is-read-from-the-internal-domain-only)).
4. If the principal is `Nothing`, set `Response = UserDoesNotExist`. Because the domain is hard-wired, an external-domain user's `SamAccountName` never resolves here, so external-domain users are always reported as `UserDoesNotExist`; the caller cannot select a domain.
5. Otherwise, get the underlying `DirectoryEntry` and assign `Message = de.Properties.Item("extensionAttribute2").Value`, a late-bound COM property read ([BR-27](../business-rules.md#br-27-a-directory-attribute-query-returns-the-value-or-userdoesnotexist), [BR-31](../business-rules.md#br-31-the-printer-attribute-is-read-from-the-internal-domain-only)).
6. `Catch`: set `Response = Failure`, `Message = ex.Message`.
7. `Finally`: release `userPrin` and `de`.
8. Return the `ADServiceResponse` sentinel.

## Process flow

```mermaid
flowchart TD
    A["Call GetUserPrinter"] --> B["GetUserPrincipal<br>inExternalDomain hard-wired False"]
    B -->|"Nothing"| C["Response = UserDoesNotExist<br>includes all external-domain users"]
    B -->|"Found"| D["Read extensionAttribute2<br>via GetUnderlyingObject"]
    D -->|"Success"| E["Message = printer value<br>Response = Success"]
    D -->|"Exception"| F["Response = Failure<br>Message = ex.Message"]
    C --> G["Return ADServiceResponse"]
    E --> G
    F --> G
```

## Shared state effects

None — this operation touches no process-wide state; all locals are per-request.

## Error handling

This operation never faults: every failure path, including an unresolved user or an unset `extensionAttribute2` attribute, is caught and mapped to `Response = Failure` with `ex.Message` in `Message`. See [Faults](../faults.md) for the service-wide fault model.

## Authorization

None in code. This is one of the eleven ungated operations that disclose directory data to any caller who can reach the endpoint (see [Authentication and authorization](../authentication-authorization.md) and [Tech debt](../tech-debt.md)).

## Related documentation
- [Service index](../index.md)
- [Overview](../overview.md)
- [Architecture](../architecture.md)
- [Activation and hosting](../activation-hosting.md)
- [Operations](../operations.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Authentication and authorization](../authentication-authorization.md)
- [Configuration](../configuration.md)
- [Dependencies](../dependencies.md)
- [Faults](../faults.md)
- [Operational runbook](../operational-runbook.md)
- [Tech debt](../tech-debt.md)

## Sources
- `src\ADUserServices\clsADUserServices.asmx.vb` (lines 687-713)
